<html lang="en">
	<head>
		<title>Yuka | Savegames</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<link rel="stylesheet" type="text/css" href="../../lib/styles.css">
		<link rel="shortcut icon" type="image/x-icon" href="https://mugen87.github.io/yuka/favicon.ico">
		<style>
			button {
				height: 20px;
				width: 100px;
				color: #ffffff;
				background: transparent;
				outline: 1px solid #ffffff;
				border: 0px;
				cursor: pointer;
			}
		</style>
	</head>
<body>

	<section id="info">
		<p>
			You can save and reload the current state of the game. The savegame is also loaded when the page is refreshed.
		</p
		<p>
			<button id="btn-save" type="button">Save</button>
			<button id="btn-load" type="button">Load</button>
			<button id="btn-clear" type="button">Clear</button>
		</p>
	</section>

	<script type="module">

		import * as YUKA from '../../../build/yuka.module.js';
		import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.109/build/three.module.js';

		import { CustomEntity } from './src/CustomEntity.js';
		import { CustomVehicle } from './src/CustomVehicle.js';

		let renderer, scene, camera;

		let entityManager, time;

		let targetMesh, vehicleMesh;

		init();
		animate();

		function init() {

			scene = new THREE.Scene();

			camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 0.1, 1000 );
			camera.position.set( 0, 0, 10 );
			camera.lookAt( scene.position );

			//

			const entityGeometry = new THREE.ConeBufferGeometry( 0.1, 0.5, 8 );
			entityGeometry.rotateX( Math.PI * 0.5 );
			const entityMaterial = new THREE.MeshNormalMaterial();

			vehicleMesh = new THREE.Mesh( entityGeometry, entityMaterial );
			vehicleMesh.matrixAutoUpdate = false;
			scene.add( vehicleMesh );

			const targetGeometry = new THREE.SphereBufferGeometry( 0.05 );
			const targetMaterial = new THREE.MeshBasicMaterial( { color: 0xff0000 } );

			targetMesh = new THREE.Mesh( targetGeometry, targetMaterial );
			targetMesh.matrixAutoUpdate = false;
			scene.add( targetMesh );

			//

			const sphereGeometry = new THREE.SphereBufferGeometry( 2, 32, 32 );
			const sphereMaterial = new THREE.MeshBasicMaterial( { color: 0xcccccc, wireframe: true, transparent: true, opacity: 0.2 } );
			const sphere = new THREE.Mesh( sphereGeometry, sphereMaterial );
			scene.add( sphere );

			//

			renderer = new THREE.WebGLRenderer( { antialias: true } );
			renderer.setPixelRatio( window.devicePixelRatio );
			renderer.setSize( window.innerWidth, window.innerHeight );
			document.body.appendChild( renderer.domElement );

			//

			window.addEventListener( 'resize', onWindowResize, false );

			const saveButton = document.getElementById( 'btn-save' );
			saveButton.addEventListener( 'click', onSave, false );

			const loadButton = document.getElementById( 'btn-load' );
			loadButton.addEventListener( 'click', onLoad, false );

			const clearButton = document.getElementById( 'btn-clear' );
			clearButton.addEventListener( 'click', onClear, false );

			// game setup

			entityManager = new YUKA.EntityManager();
			time = new YUKA.Time();

			// register custom types so the entity manager is able to instantiate
			// custom objects from JSON

			entityManager.registerType( 'CustomEntity', CustomEntity );
			entityManager.registerType( 'CustomVehicle', CustomVehicle );

			if ( hasSavegame() ) {

				// load an existing savegame

				onLoad();

			} else {

				const target = new CustomEntity();
				target.setRenderComponent( targetMesh, sync );
				target.generatePosition();

				const vehicle = new CustomVehicle();
				vehicle.target = target;
				vehicle.setRenderComponent( vehicleMesh, sync );

				const seekBehavior = new YUKA.SeekBehavior( target.position );
				vehicle.steering.add( seekBehavior );

				entityManager.add( target );
				entityManager.add( vehicle );

			}

		}

		function onWindowResize() {

			camera.aspect = window.innerWidth / window.innerHeight;
			camera.updateProjectionMatrix();

			renderer.setSize( window.innerWidth, window.innerHeight );

		}

		function animate() {

			requestAnimationFrame( animate );

			time.update();

			const delta = time.getDelta();

			entityManager.update( delta );

			renderer.render( scene, camera );

		}

		function sync( entity, renderComponent ) {

			renderComponent.matrix.copy( entity.worldMatrix );

		}

		function onSave() {

			const json = entityManager.toJSON();
			const jsonString = JSON.stringify( json );

			localStorage.setItem( 'yuka_savegame', jsonString );

		}

		function onLoad() {

			const jsonString = localStorage.getItem( 'yuka_savegame' );

			if ( jsonString !== null ) {

				try {

					const json = JSON.parse( jsonString );
					entityManager.fromJSON( json );

					// restore render components (depends on 3D engine)

					const target = entityManager.getEntityByName( 'target' );
					target.setRenderComponent( targetMesh, sync );

					const vehicle = entityManager.getEntityByName( 'vehicle' );
					vehicle.setRenderComponent( vehicleMesh, sync );

				} catch ( e ) {

					console.error( e );
					onClear();
					alert( 'Invalid Savegame found. Savegame was deleted.' );
					window.location.reload();

				}


			}

		}

		function onClear() {

			localStorage.removeItem( 'yuka_savegame' );

		}

		function hasSavegame() {

			return localStorage.getItem( 'yuka_savegame' ) !== null;

		}

	</script>

</body>
</html>
